package org.lichsword.ux.ui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.HeadlessException;
import java.awt.Toolkit;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;

import org.lichsword.ux.manager.BuildProcessListener;
import org.lichsword.ux.manager.IconCachedManager;
import org.lichsword.ux.manager.file.RefactorFileManager;
import org.lichsword.ux.model.ButtonInfo;
import org.lichsword.ux.util.DragFileHandler;
import org.lichsword.ux.util.FileUtil;
import org.lichsword.ux.util.TipUtil;

public class Launcher extends JFrame {

	public static void main(String args[]) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					Launcher frame = new Launcher();
					frame.setVisible(true);

				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * @throws HeadlessException
	 */
	public Launcher() throws HeadlessException {
		super();
		initContentView();
	}

	private JPanel mContentPane;
	private JTextField mKeywordEditText;
	private JLabel mDefaultPiclabel;
	private JLabel mPressedPiclabel;
	private JLabel mDisabledPiclabel;
	private JButton mConfirmButton;
	private JTextArea mProcessTextArea;
	private JLabel mDefaultPicDescLabel;
	private JLabel mPressedPicDescLabel;
	private JLabel mDisabledPicDescLabel;
	private JCheckBox mAutoOpenDirCheckBox;
	private JLabel mTipLabel;
	private JCheckBox mAutoResetChcekBox;
	private JCheckBox mDefaultPictureCheckBox;
	private JCheckBox mPressedPictureCheckBox;
	private JCheckBox mDisabledPictureCheckBox;

	private DragFileHandler mDefaultPicDragFileHandler = new DragFileHandler() {

		/**
		 * 
		 */
		private static final long serialVersionUID = 1L;

		@Override
		public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
			return super.canImport(comp, transferFlavors);
		}

		@SuppressWarnings("unchecked")
		@Override
		public boolean importData(JComponent comp, Transferable t) {
			try {

				List dragFileList = (List) t
						.getTransferData(DataFlavor.javaFileListFlavor);
				String filePath = loadDragFiles(dragFileList);
				dragFileEventHappened(filePath, ButtonInfo.PIC_DEFAULT);
			} catch (UnsupportedFlavorException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			return super.importData(comp, t);
		}

	};

	private DragFileHandler mPressedPicDragFileHandler = new DragFileHandler() {

		/**
		 * 
		 */
		private static final long serialVersionUID = 2L;

		@Override
		public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
			return super.canImport(comp, transferFlavors);
		}

		@SuppressWarnings("unchecked")
		@Override
		public boolean importData(JComponent comp, Transferable t) {
			try {

				List dragFileList = (List) t
						.getTransferData(DataFlavor.javaFileListFlavor);
				String filePath = loadDragFiles(dragFileList);
				dragFileEventHappened(filePath, ButtonInfo.PIC_PRESSED);
			} catch (UnsupportedFlavorException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			return super.importData(comp, t);
		}

	};

	private DragFileHandler mDisabledPicDragFileHandler = new DragFileHandler() {

		/**
		 * 
		 */
		private static final long serialVersionUID = 3L;

		@Override
		public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) {
			return super.canImport(comp, transferFlavors);
		}

		@SuppressWarnings("unchecked")
		@Override
		public boolean importData(JComponent comp, Transferable t) {
			try {

				List dragFileList = (List) t
						.getTransferData(DataFlavor.javaFileListFlavor);
				String filePath = loadDragFiles(dragFileList);
				dragFileEventHappened(filePath, ButtonInfo.PIC_DISABLED);
			} catch (UnsupportedFlavorException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			return super.importData(comp, t);
		}

	};

	@SuppressWarnings("unchecked")
	private String loadDragFiles(List dragFileList) {
		String filePath = null;
		for (Iterator iter = dragFileList.iterator(); iter.hasNext();) {
			File file = (File) iter.next();
			filePath = file.getPath();
			break;
		}
		return filePath;
	}

	private boolean dragFileEventHappened(String filePath, int whichPic) {
		if (!FileUtil.isSupportPicType(filePath)) {
			System.out
					.println("Not belong supported picture type[9.png/png/jpg]...ERROR");
			return false;
		}// end if

		// cached icon
		IconCachedManager.getInstance()
				.DragFileChangeHappen(filePath, whichPic);
		// cached icon info
		switch (whichPic) {
		case ButtonInfo.PIC_DEFAULT:
			System.out.println("default pic : " + filePath);
			mDefaultPiclabel.setIcon(IconCachedManager.getInstance().getIcon(
					filePath));
			break;
		case ButtonInfo.PIC_PRESSED:
			System.out.println("pressed pic : " + filePath);
			mPressedPiclabel.setIcon(IconCachedManager.getInstance().getIcon(
					filePath));
			break;
		case ButtonInfo.PIC_DISABLED:
			System.out.println("disabled pic : " + filePath);
			mDisabledPiclabel.setIcon(IconCachedManager.getInstance().getIcon(
					filePath));
			break;
		default:
			break;
		}
		return true;
	}

	private ActionListener mConfirmActionListener = new ActionListener() {

		@Override
		public void actionPerformed(ActionEvent e) {
			System.out.println("You click confirm button...OK");
			String keyword = mKeywordEditText.getText();
			if (FileUtil.isKeywordSafe(keyword)) {
				if (preCheckButtonInfo()) {
					IconCachedManager.getInstance().confirmBuild(keyword);
				}// end if
			} else {
				System.out
						.println("Keyword contain illegal char, only allow [0~9] OR [a~z] OR '_'");
				showTip(TipUtil.ERROR_CONTAIN_ILLEGAL_CHAR);
			}
		}

	};

	private boolean preCheckButtonInfo() {
		boolean canPassCheck = true;

		String tip = IconCachedManager.getInstance().preCheckButtonInfo(
				mDefaultPictureCheckBox.isSelected(),
				mPressedPictureCheckBox.isSelected(),
				mDisabledPictureCheckBox.isSelected());
		if (!tip.equals(TipUtil.INFO_CHECK_PICTIRE_PASSED)) {
			showTip(tip);
			canPassCheck = false;
		} else {
			canPassCheck = true;
		}
		return canPassCheck;
	}

	private KeyListener mKeywordKeyListener = new KeyListener() {

		@Override
		public void keyPressed(KeyEvent e) {
		}

		@Override
		public void keyReleased(KeyEvent e) {
		}

		@Override
		public void keyTyped(KeyEvent e) {
			System.out.println("You typed " + e.getKeyChar());
			char ch = e.getKeyChar();
			if (FileUtil.isCharSafe(ch)) {
				hideTip();
			} else {
				System.out
						.println("Illegal character input: "
								+ ch
								+ "[Only support ：1.number(0~9) 2.low char(a~z) 3.underline(_)]");
				showTip(TipUtil.ERROR_CONTAIN_ILLEGAL_CHAR);
			}
			refreshPicDesc(mKeywordEditText.getText());
		}

	};

	private void refreshPicDesc(String keyword) {
		//
		String pressedText = IconCachedManager.getInstance().getRefactName(
				keyword, ButtonInfo.PIC_PRESSED);
		mPressedPicDescLabel.setText(pressedText);
		//
		String disabledText = IconCachedManager.getInstance().getRefactName(
				keyword, ButtonInfo.PIC_DISABLED);
		mDisabledPicDescLabel.setText(disabledText);
		//
		String defauledText = IconCachedManager.getInstance().getRefactName(
				keyword, ButtonInfo.PIC_DEFAULT);
		mDefaultPicDescLabel.setText(defauledText);
	}

	@SuppressWarnings("unused")
	private boolean limitKeywordSafe(String src) {
		byte[] buffer = new byte[100];

		int index = 0;
		// limit to no space char
		byte[] bytes = src.getBytes();
		for (int i = 0; i < bytes.length; i++) {
			byte temp = bytes[i];
			if (temp >= 'A' && temp <= 'Z') {
				// limit to lowcase
				temp += 32;
			} else if (temp >= '0' && temp <= '9') {
				// allow, do nothing
			} else if (temp == '_') {
				// allow, do nothing
			} else if (temp >= 'a' && temp <= 'z') {
				// allow, do nothing
			} else {
				continue;
			}
			buffer[index] = bytes[i];
			index++;
		}
		mKeywordEditText.setText(new String(buffer, 0, index));
		return true;
	}

	private BuildProcessListener mBuildProcessListener = new BuildProcessListener() {

		@Override
		public void buildBegin(String msg) {
			enableAllCompoment(false);
			mProcessTextArea.setText("");
		}

		@Override
		public void buildEnd(String msg) {
			enableAllCompoment(true);
			if (mAutoOpenDirCheckBox.isSelected()) {
				FileUtil.autoOpenDir(RefactorFileManager.getInstance()
						.getTargetDrawableDirPath());
				FileUtil.autoOpenDir(RefactorFileManager.getInstance()
						.getTargetDrawableHdpiDirPath());
				System.out
						.println("Auto open folder HAS select, auto open folder...OK");
			} else {
				System.out
						.println("Auto open folder is NOT select, so do nothing...OK");
			}

			if (mAutoResetChcekBox.isEnabled()) {
				IconCachedManager.getInstance().clearAllInfo();
				resetAllCompoment();
			}// end if
		}

		@Override
		public void buildProcess(String msg, int color) {
			if (null != msg) {
				mProcessTextArea.append(msg);
				mProcessTextArea.append("\n");
			}// end if
		}

	};

	private void enableAllCompoment(boolean enable) {
		mConfirmButton.setEnabled(enable);
		mDefaultPiclabel.setEnabled(enable);
		mPressedPiclabel.setEnabled(enable);
		mDisabledPiclabel.setEnabled(enable);
	}

	private void resetAllCompoment() {
		mDefaultPicDescLabel.setText("");
		mPressedPicDescLabel.setText("");
		mDisabledPicDescLabel.setText("");
		mTipLabel.setText("");
		mDefaultPiclabel.setIcon(null);
		mPressedPiclabel.setIcon(null);
		mDisabledPiclabel.setIcon(null);
		mKeywordEditText.setText("");
	}

	private void showTip(String tipMsg) {
		mTipLabel.setText(tipMsg);
	}

	private void hideTip() {
		mTipLabel.setText("");
	}

	/**
	 * Create the frame.
	 */
	private void initContentView() {
		initFrameParam();
		//
		mContentPane = new JPanel();
		mContentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(mContentPane);
		mContentPane.setLayout(null);

		mDefaultPiclabel = new JLabel("Default Picture");
		mDefaultPiclabel.setBackground(Color.WHITE);
		mDefaultPiclabel.setBounds(24, 5, 120, 120);
		mDefaultPiclabel.setTransferHandler(mDefaultPicDragFileHandler);
		mContentPane.add(mDefaultPiclabel);

		mPressedPiclabel = new JLabel("Pressed Picture");
		mPressedPiclabel.setBackground(Color.ORANGE);
		mPressedPiclabel.setBounds(215, 5, 120, 120);
		mPressedPiclabel.setTransferHandler(mPressedPicDragFileHandler);
		mContentPane.add(mPressedPiclabel);

		mDisabledPiclabel = new JLabel("Disabled Picture");
		mDisabledPiclabel.setBackground(Color.DARK_GRAY);
		mDisabledPiclabel.setBounds(400, 5, 120, 120);
		mDisabledPiclabel.setTransferHandler(mDisabledPicDragFileHandler);
		mContentPane.add(mDisabledPiclabel);

		mConfirmButton = new JButton("Confirm");
		mConfirmButton.setFont(new Font("Tahoma", Font.PLAIN, 18));
		mConfirmButton.setBounds(350, 207, 160, 45);
		mConfirmButton.addActionListener(mConfirmActionListener);
		mContentPane.add(mConfirmButton);

		mProcessTextArea = new JTextArea();
		mProcessTextArea.setEditable(false);
		mProcessTextArea.setLineWrap(true);
		mProcessTextArea.setWrapStyleWord(true);
		mProcessTextArea.setBounds(15, 207, 300, 198);
		mContentPane.add(mProcessTextArea);

		mDefaultPicDescLabel = new JLabel();
		mDefaultPicDescLabel.setBounds(15, 124, 160, 24);
		mContentPane.add(mDefaultPicDescLabel);

		mPressedPicDescLabel = new JLabel();
		mPressedPicDescLabel.setBounds(204, 124, 160, 24);
		mContentPane.add(mPressedPicDescLabel);

		mDisabledPicDescLabel = new JLabel();
		mDisabledPicDescLabel.setBounds(387, 124, 160, 24);
		mContentPane.add(mDisabledPicDescLabel);

		mAutoOpenDirCheckBox = new JCheckBox("Auto open folder");
		mAutoOpenDirCheckBox.setSelected(true);
		mAutoOpenDirCheckBox.setBounds(350, 259, 163, 23);
		mContentPane.add(mAutoOpenDirCheckBox);

		JLabel label2 = new JLabel("Sort progress :");
		label2.setBounds(15, 180, 182, 26);
		mContentPane.add(label2);

		JLabel label1 = new JLabel("Input keyword:");
		label1.setBounds(350, 349, 139, 14);
		mContentPane.add(label1);

		mKeywordEditText = new JTextField();
		mKeywordEditText.setBounds(350, 374, 160, 31);
		mKeywordEditText.addKeyListener(mKeywordKeyListener);
		mContentPane.add(mKeywordEditText);
		mKeywordEditText.setColumns(10);

		mTipLabel = new JLabel();
		mTipLabel.setFont(new Font("Monospaced", Font.BOLD, 13));
		mTipLabel.setForeground(Color.RED);
		mTipLabel.setBounds(15, 416, 532, 24);
		mContentPane.add(mTipLabel);
		hideTip();

		mAutoResetChcekBox = new JCheckBox("Auto reset after finish");
		mAutoResetChcekBox.setBounds(350, 285, 163, 23);
		mContentPane.add(mAutoResetChcekBox);

		mDefaultPictureCheckBox = new JCheckBox("check defult picture");
		mDefaultPictureCheckBox.setBounds(12, 155, 163, 23);
		mContentPane.add(mDefaultPictureCheckBox);

		mPressedPictureCheckBox = new JCheckBox("check pressed picture");
		mPressedPictureCheckBox.setBounds(204, 155, 163, 23);
		mContentPane.add(mPressedPictureCheckBox);

		mDisabledPictureCheckBox = new JCheckBox("check disabled picture");
		mDisabledPictureCheckBox.setBounds(387, 155, 163, 23);
		mContentPane.add(mDisabledPictureCheckBox);

		// init set listener
		initListeners();
	}

	private final String FRAME_TITLE = "UXTool v1.0.0";

	/**
	 * Center in screen
	 */
	private void initFrameParam() {
		setTitle(FRAME_TITLE);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 606, 484);

		Toolkit kit = Toolkit.getDefaultToolkit();
		Dimension screenSize = kit.getScreenSize();

		int width = screenSize.width;
		int height = screenSize.height;

		int left = (width - getSize().width) / 2;
		int top = (height - getSize().height) / 2;

		setLocation(left, top);
		setResizable(false);
	}

	private void initListeners() {
		IconCachedManager.getInstance().setBuildProcessListener(
				mBuildProcessListener);
	}
}